from py2neo import Graph
import os
import difflib  # 使用标准库进行字符串匹配
from dotenv import load_dotenv

load_dotenv()


class FaultMatcher:
    def __init__(self):
        self.graph = Graph(
            os.getenv("NEO4J_URI"),
            auth=(os.getenv("NEO4J_USER"), os.getenv("NEO4J_PASSWORD"))
        )
        self.standard_faults = self.get_knowledge_graph_fault_types()

    def get_knowledge_graph_fault_types(self):
        """从知识图谱查询所有标准故障类型名称及描述"""
        cypher = """
        MATCH (f:FaultType)
        RETURN f.name AS fault_type, f.description AS description
        """
        result = self.graph.run(cypher).data()
        return {item["fault_type"]: item["description"] for item in result}

    def match_standard_fault(self, user_input):
        """使用字符串相似度匹配标准故障（基于知识图谱）"""
        if not self.standard_faults:
            return None

        best_match = None
        highest_score = 0.5  # 设置最低匹配阈值
        user_input_norm = user_input.lower().strip()

        for fault_name, fault_desc in self.standard_faults.items():
            # 计算名称相似度
            name_score = difflib.SequenceMatcher(
                None, fault_name.lower(), user_input_norm
            ).ratio()

            # 计算描述相似度（增强匹配准确性）
            desc_score = 0
            if fault_desc:
                desc_score = difflib.SequenceMatcher(
                    None, fault_desc.lower(), user_input_norm
                ).ratio() * 0.3  # 描述权重较低

            total_score = name_score + desc_score
            if total_score > highest_score:
                highest_score = total_score
                best_match = fault_name

        return best_match

    def get_fault_details(self, fault_name):
        """获取标准故障的详细信息，供大模型使用"""
        cypher = """
        MATCH (f:FaultType {name: $fault_name})
        OPTIONAL MATCH (f)-[:HAS_ROOT_CAUSE]->(r:RootCause)
        OPTIONAL MATCH (f)-[:HAS_SOLUTION]->(s:Solution)
        RETURN f.name AS fault_name,
               f.description AS description,
               r.description AS root_cause,
               collect(s.content) AS solutions
        """
        result = self.graph.run(cypher, fault_name=fault_name).data()
        return result[0] if result else None


